package com.sunlands.deskmate.message.handler.dispatcher.impl;

import com.sunlands.deskmate.channel.ChannelInfo;
import com.sunlands.deskmate.channel.ChannelManager;
import com.sunlands.deskmate.channel.WebSocketServerHandler;
import com.sunlands.deskmate.message.entity.Messages;
import com.sunlands.deskmate.message.enums.MessageType;
import com.sunlands.deskmate.message.handler.dispatcher.Dispatcher;
import com.sunlands.deskmate.message.handler.sender.http.HttpMessagesSender;
import com.sunlands.deskmate.message.handler.storager.unsync.UnsyncMessageStorager;
import com.sunlands.deskmate.service.DialogRecordServiceImpl;
import com.sunlands.deskmate.utils.IdGenerator;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RMapCache;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import static com.sunlands.deskmate.config.RabbitMqConfig.EVENT_EXCHANGE_LOOKUP;
import static com.sunlands.deskmate.message.enums.MessageType.ENTER_GROUP;
import static com.sunlands.deskmate.message.enums.MessageType.QUIT_GROUP;

@Slf4j
@Component
public class GroupMessageDispatcher implements Dispatcher {

    @Autowired
    private DialogRecordServiceImpl dialogRecordService;

    @Autowired
    private UnsyncMessageStorager unsyncMessageStorager;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private HttpMessagesSender httpMessagesSender;

    @Override
    public void dispatcher(Messages messages) {

        if(ENTER_GROUP.getType().equals(messages.getType())
                || QUIT_GROUP.getType().equals(messages.getType())){
            return;
        }

        String roomId = messages.getToId();
        String key = WebSocketServerHandler.getRoomKey(messages.getType(), roomId);
        Set<Long> members = dialogRecordService.refreshMembers(key);
        RMapCache<String, ChannelInfo> redisChannelStore = ChannelManager.getRedisChannelStore();

        Long oldAckId = messages.getAckId();
        messages.setAckId(IdGenerator.id());
        log.info("1.2 防止消息乱序，将消息进行转换 重新生成ackId oldAckId = {} newAckId = {}", oldAckId, messages.getAckId());

//        Long oldAckId = messages.getAckId();
        List<Long> hasSend = new ArrayList<>();

        //先推送会话中的用户
        for (Object userId : members) {
            messages.setRealToId(Long.parseLong(userId.toString()));
//            messages.setAckId(IdGenerator.id());
            ChannelInfo channelInfo = new ChannelInfo(messages.getRealToId());
            boolean success = unsyncMessageStorager.add(channelInfo.getSessionKey(), messages, messages.getAckId());

            if (success) {
                ChannelInfo info = redisChannelStore.get(channelInfo.getSessionKey());
                //通道信息为空的话，不通知发送消息，再次连上通道后会重新发送
                if (Objects.isNull(info)) {
                    log.error("发送方redis channel为空，出现异常 messages = {}", messages);
                    continue;
                }
                log.info("2、群消息 转为新的消息 条数 members = {} msgEntity = {},", members.size(), messages);
                rabbitTemplate.convertAndSend(EVENT_EXCHANGE_LOOKUP, info.getWorkId().toString(), messages);
            }
            hasSend.add(messages.getRealToId());
        }

        List<Long> allUsers = dialogRecordService.getUserIdsByToId(messages.getFromUserId(), messages.getToId(), messages.getType());

        allUsers.removeAll(hasSend);
        log.info("群消息推送离线消息用户 allUsers = {} 已经发送socket消息的用户 hasSend = {}", allUsers, hasSend);
        sendHttpMessage(allUsers, messages);

    }


    public void sendHttpMessage(List<Long> allUsers, Messages messages) {
        //其余用户发送离线消息
        if (MessageType.SHARE_GROUP_TO_PRIVATE.getType().equals(messages.getType())
                || MessageType.SHARE_ROOM_TO_PRIVATE.getType().equals(messages.getType())
                || MessageType.SHARE_DIARY_TO_PRIVATE.getType().equals(messages.getType())
                || MessageType.SHARE_DIARY_COMMENT_TO_PRIVATE.getType().equals(messages.getType())
                || MessageType.SHARE_GROUP_TO_GROUP.getType().equals(messages.getType())
                || MessageType.SHARE_ROOM_TO_GROUP.getType().equals(messages.getType())
                || MessageType.SHARE_DIARY_TO_GROUP.getType().equals(messages.getType())
                || MessageType.SHARE_DIARY_COMMENT_TO_GROUP.getType().equals(messages.getType())
                || MessageType.SHARE_GROUP_TO_ROOM.getType().equals(messages.getType())
                || MessageType.SHARE_ROOM_TO_ROOM.getType().equals(messages.getType())
                || MessageType.SHARE_DIARY_TO_ROOM.getType().equals(messages.getType())
                || MessageType.GROUP_CHAT.getType().equals(messages.getType())
                || MessageType.PRIVATE_CHAT.getType().equals(messages.getType())
                || MessageType.ROOM_CHAT.getType().equals(messages.getType())
                || MessageType.APPLY_PUBLISH.getType().equals(messages.getType())
                || MessageType.SHARE_DIARY_COMMENT_TO_ROOM.getType().equals(messages.getType())) {
            allUsers.remove(Long.valueOf(messages.getFromUserId()));
        }

        if (allUsers.size() <= 0) {
            return;
        }

        // 推送离线消息和通知
        httpMessagesSender.doPushMessage(messages, allUsers);
        if (httpMessagesSender.filterPushInform(messages.getType())) {
            httpMessagesSender.doPushInform(messages, allUsers);
        }

        //给在线用户推送socket，让客户端拉去离线消息
//        for (Long userId : allUsers) {
//            Long id = IdGenerator.id();
//            Messages notice = Messages.builder()
//                    .ackId(id)
//                    .id(id.toString())
//                    .toId(userId.toString())
//                    .realToId(userId)
//                    .createTime(DateUtil.getStringDate())
//                    .type(MessageType.NOTICE_EVENT.getType())
//                    .build();
//            ChannelInfo channelInfo = new ChannelInfo(notice.getRealToId());
//            ChannelInfo info = redisChannelStore.get(channelInfo.getSessionKey());
//            if (Objects.nonNull(info)) {
//                unsyncMessageStorager.add(channelInfo.getSessionKey(), notice, notice.getAckId());
//                rabbitTemplate.convertAndSend(EVENT_EXCHANGE_LOOKUP, info.getWorkId().toString(), notice);
//                log.info("2、群消息（离线） 发送离线消息 转为新的消息 notice = {},", notice);
//            }
//
//        }
    }


}
